package com.lckj.android.shell.ui.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Keep;
import androidx.annotation.Nullable;

import com.lckj.android.shell.R;

/**
 * @author lc. 2023-10-22 17:04
 */
public class ProgressView extends View {

    private static final int MAX = 100;

    private static final int STYLE_RECT = 0;
    private static final int STYLE_RECT_OVAL = 1;

    /*** 进度结束，自动隐藏 */
    private boolean mAutoInvisibleOnFinish = true;

    /*** 背景色 */
    private int mBackgroundColor;
    /*** 进度颜色 */
    private int mProgressColor;
    /*** 描边颜色 */
    private int mStrokeColor;
    /*** 描边大小 */
    private int mStrokeWidth;
    /*** 进度样式 */
    private int mStyle;

    /*** 当前进度 */
    private float mProgress;

    private final RectF mRectF = new RectF();
    private final RectF mArcRectF = new RectF();
    private Paint mPaint;

    public ProgressView(Context context) {
        this(context, null);
    }

    public ProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, @Nullable AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressView);
        mBackgroundColor = a.getColor(R.styleable.ProgressView_progressViewBackgroundColor, Color.TRANSPARENT);
        mProgressColor = a.getColor(R.styleable.ProgressView_progressViewColor, Color.TRANSPARENT);
        mStrokeColor = a.getColor(R.styleable.ProgressView_progressViewStrokeColor, Color.TRANSPARENT);
        mStrokeWidth = a.getDimensionPixelSize(R.styleable.ProgressView_progressViewStrokeWidth, 0);
        mStyle = a.getInt(R.styleable.ProgressView_progressViewStyle, STYLE_RECT);
        mAutoInvisibleOnFinish = a.getBoolean(R.styleable.ProgressView_progressViewAutoHideOnFinish, true);
        a.recycle();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
    }

    /**
     * 设置是否加载完成后，自动隐藏。默认 true
     *
     * @param autoInvisibleOnFinish true-加载完成后自动隐藏
     */
    public void setAutoInvisibleOnFinish(boolean autoInvisibleOnFinish) {
        mAutoInvisibleOnFinish = autoInvisibleOnFinish;
    }

    /**
     * 设置颜色
     *
     * @param backgroundColor 背景色
     * @param progressColor   进度色
     */
    public void setColor(int backgroundColor, int progressColor) {
        mBackgroundColor = backgroundColor;
        mProgressColor = progressColor;
    }

    /**
     * 设置进度条颜色
     *
     * @param progressColor 进度条颜色
     */
    @Keep
    public void setProgressColor(int progressColor) {
        if (progressColor == mProgressColor) {
            return;
        }
        mProgressColor = progressColor;
        postInvalidate();
    }

    /**
     * 设置进度条背景颜色
     *
     * @param bgColor 进度条背景颜色
     */
    @Keep
    public void setProgressBgColor(int bgColor) {
        if (bgColor == mBackgroundColor) {
            return;
        }
        mBackgroundColor = bgColor;
        postInvalidate();
    }

    /**
     * 设置进度
     *
     * @param progress 进度 [0,100]
     */
    @Keep
    public void setProgress(float progress) {
        // progress 最大 100
        progress = Math.min(progress, MAX);
        // 加载完成，根据配置自动隐藏
        setVisibility(progress == MAX && mAutoInvisibleOnFinish ? INVISIBLE : VISIBLE);
        // 设置当前进度，绘制
        mProgress = progress;
        postInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();

        // 背景
        mPaint.setColor(mBackgroundColor);
        mPaint.setStyle(Paint.Style.FILL);
        mRectF.set(0, 0, width, height);
        if (mStyle == STYLE_RECT_OVAL) {
            canvas.drawRoundRect(mRectF, height, height, mPaint);
        } else {
            canvas.drawColor(mBackgroundColor);
        }

        // 描边
        if (mStrokeWidth > 0) {
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(mStrokeWidth);
            mPaint.setColor(mStrokeColor);

            float strokeHalf = mStrokeWidth * 0.5f;
            mRectF.left = mRectF.left + strokeHalf;
            mRectF.right = mRectF.right - strokeHalf;
            mRectF.top = mRectF.top + strokeHalf;
            mRectF.bottom = mRectF.bottom - strokeHalf;

            if (mStyle == STYLE_RECT_OVAL) {
                canvas.drawRoundRect(mRectF, height, height, mPaint);
            } else {
                canvas.drawRect(mRectF, mPaint);
            }
        }

        int left = mStrokeWidth;
        int top = mStrokeWidth;
        int right = (int) ((width - mStrokeWidth * 2) * (mProgress / 100.0f) + mStrokeWidth);
        int bottom = height - mStrokeWidth;

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mProgressColor);
        mRectF.set(left, top, right, bottom);
        if (mStyle == STYLE_RECT_OVAL) {
            if (mRectF.width() < mRectF.height()) {
                mArcRectF.left = mRectF.left;
                mArcRectF.right = mRectF.right;
                float radius = mRectF.height() / 2f;
                float l1 = radius - mArcRectF.width() / 2f;

                mArcRectF.left = mRectF.left;
                mArcRectF.right = mRectF.left + mRectF.height();
                mArcRectF.top = mRectF.top;
                mArcRectF.bottom = mRectF.bottom;

                // 绘制左面的圆弧
                float d = (float) Math.toDegrees(Math.acos(l1 / radius));
                canvas.drawArc(mArcRectF, 180f - d, d * 2, false, mPaint);

                // 绘制右面的圆弧
                mArcRectF.offset(mRectF.width() - mArcRectF.width() - 1, 0);
                canvas.drawArc(mArcRectF, 360f - d, d * 2, false, mPaint);
            } else {
                canvas.drawRoundRect(mRectF, height, height, mPaint);
            }
        } else {
            canvas.drawRect(mRectF, mPaint);
        }
    }
}
